package com.zzw.filters.httpfilters;

import com.zzw.requestcontext.RequestContext;
import com.zzw.utils.IpUtils;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.Ordered;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.UUID;

/**
 * @author zzw
 */
public class DefaultRequestContextFilter extends OncePerRequestFilter implements Ordered {

    private static final Logger logger = LoggerFactory.getLogger(DefaultRequestContextFilter.class);

    private static final ThreadLocal<RequestContext> FILTER_REQUEST_CONTEXT = new ThreadLocal<>();

    public static RequestContext getRequestContext() {
        return FILTER_REQUEST_CONTEXT.get();
    }

    @Override
    public int getOrder() {
        return 0;
    }

    private String generateSn() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }


    @Override
    @SuppressWarnings("DuplicatedCode")
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        LocalDateTime requestTime = LocalDateTime.now();
        String requestId = generateSn();
        String ip = IpUtils.tryGetRealIp(request);
        logger.info("request context filter start，ip:{},request time:{}", ip, requestTime);
        RequestContext requestContext = new RequestContext();
        requestContext.setRequestTime(requestTime);
        requestContext.setIp(ip);
        requestContext.setSn(requestId);
        FILTER_REQUEST_CONTEXT.set(requestContext);
        filterChain.doFilter(request, response);
        logger.info("request context filter end,cost time :{}", (ChronoUnit.MILLIS.between(requestTime, LocalDateTime.now())));
        try {
            FILTER_REQUEST_CONTEXT.remove();
        } catch (Exception ignore) {

        }
    }
}
